package org.argus.common.web.core.feign;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import feign.Response;
import feign.Util;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;
import org.argus.common.core.exception.FeignProcessException;
import org.argus.common.core.domain.R;
import org.springframework.http.HttpStatus;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

/**
 * @Author 刘文/Cliff Liu
 * @Date 2024/7/29
 */
@Slf4j
public class ResponseDecoder implements Decoder {

    private final ObjectMapper objectMapper;

    public ResponseDecoder() {
        this.objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        if (response.status() == HttpStatus.NOT_FOUND.value()) {
            log.error("Destination service is not found.");
            return Util.emptyValueOf(type);
        }
        if (response.body() == null) {
            return null;
        }
        R r = objectMapper.readValue(response.body().asReader(StandardCharsets.UTF_8), R.class);
        if (r.getCode() == R.SUCCESS) {
            // Java原生类型，直接返回
            if (type != null && type.getTypeName().startsWith("java.lang")) {
                return r.getData();
            }
            return objectMapper.readValue(objectMapper.writeValueAsString(r.getData()), objectMapper.constructType(type));
        }

        log.error("Feign request failed, code=" + r.getCode() + ", msg=" + r.getMsg());
        // 非请求处理成功
        // 有body，直接用body
        if (r.getData() != null) {
            throw new FeignProcessException(r.getCode(), r.getData().toString());
        }

        throw new FeignProcessException(r.getCode(), r.getMsg());
    }
}
